//
// Created by Martin on 2022/10/3.
//
#include <iostream>
#include <cassert>
using namespace std;

struct A
{
    virtual ~A(){};
    virtual void func()
    {
        cout << "A::func" << endl;
    }
    bool operator==(const A& other)
    {
        return true;
    }
};
struct B : A
{
    void func() override
    {
        cout << "B::func" << endl;
    }
};

// 接收指针参数版本
// e.g. Source: A*, Target: B*
template<class Target, class Source>
inline Target polymorphic_downcast(Source* x)
{
    // why ok?
    assert(dynamic_cast<Target>(x) == x);
    return static_cast<Target>(x);
}

// 接收引用参数版本
// e.g. Source: A&, Target: B&
template <typename Target, typename Source>
inline Target polymorphic_downcast(Source& x)
{
    // why error?
    // 2个引用比较, 会调用operator==
    // assert(dynamic_cast<Target>(x) == x);

    assert(
            dynamic_cast<
            typename add_pointer<typename remove_reference<Target>::type
                    >::type>(&x)
            == &x);
    return static_cast<Target>(x);
}



static void test_polymorphic_downcast()
{
    cout << "test case1" << endl;
    B b;
    A* a_ptr = &b;
    B* b_ptr = polymorphic_downcast<B*>(a_ptr);
    b_ptr->func();

    cout << "test case2" << endl;
    A& a_ref = b;
    B& b_ref = polymorphic_downcast<B&>(a_ref);
    b_ref.func();

    auto& c = dynamic_cast<B&>(a_ref);
    c.func();
}

int main()
{
    test_polymorphic_downcast();
    return 0;
}
